//
// Created by jaesonzhang on 2024/9/11.
//

#ifndef SKIACANVASJSBINDING_JSAPP_H
#define SKIACANVASJSBINDING_JSAPP_H


#include <jni.h>
#include <__memory/shared_ptr.h>

#include <iostream>
#include <string>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <queue>
#include <functional>
#include <future>
#include "../quickjs/quickjs.h"
#include  "JSEngine.h"
#include "RenderEvent.h"
#include "EventBus.h"
#include "RenderCallback.h"

#include "include/core/SkPaint.h"
#include <include/core/SkBitmap.h>
#include <include/core/SkFont.h>
#include "include/core/SkCanvas.h"
#include "include/core/SkFontMgr.h"
#include "gpu/gl/GrGLTypes.h"

#include <android/bitmap.h>
#include <android/native_window.h>
#include <android/native_window_jni.h>


class JSApp: public RenderCallback, public std::enable_shared_from_this<JSApp> {
 public:
  JSApp(jobject jsApp);
  ~JSApp();
  void start();
  void stop();
  void destroy();
  void halt();
  void resume();
  void attachSurface(jobject surface, int width, int height);
  void detachSurface(jobject surface);
  void render(bool shouldAttach = true);
  int getWidth() { return width; };
  int getHeight() { return height; };
  void registerJSAppObject(JSValue *jsValue) {
    if (this->jsAppValue) {
      JS_FreeValue(jsEngine->jsContext, *jsAppValue);
    }
    this->jsAppValue = jsValue;
  }

 public:
  void onRender() override;
  void requestRender(SkBitmap bitmap, int w, int h);
  void callJSMethod(const char *method);

 private:
  void renderCache();
  void doCreateJSApp(int w, int h);

 public:
  bool forceRender = true;

 private:
  jobject jsApp = nullptr;
  jobject jSurface = nullptr;
  JSValue *jsAppValue = nullptr;
  int width = 0;
  int height = 0;
  SkBitmap cacheBitmap;
  std::shared_ptr<JSEngine> jsEngine;
  std::string jsCode;

};


#endif //SKIACANVASJSBINDING_JSAPP_H
